﻿#include "guild_service_query_context.h"
#include <vector>

#include "GuildModuleBrief_struct.h"
#include "GuildMember_struct.h"
#include "GuildModuleMembers_struct.h"

#include "GuildApplicationInfo_struct.h"
#include "GuildModuleApplication_struct.h"

#include "GetGuildApplicationArg_struct.h"
#include "GetGuildApplicationRes_struct.h"
#include "GetGuildBriefArg_struct.h"
#include "GetGuildBriefListArg_struct.h"
#include "GetGuildBriefListRes_struct.h"
#include "GetGuildBriefRes_struct.h"
#include "GetGuildMemberArg_struct.h"
#include "GetGuildMemberRes_struct.h"
#include "SearchGuildArg_struct.h"
#include "SearchGuildRes_struct.h"
#include "GetGuildMembersArg_struct.h"
#include "GetGuildMembersRes_struct.h"

#include "GuildRepositoryCellRoleView_struct.h"
#include "GuildRepositoryAuctionRoleView_struct.h"
#include "GuildRepositoryAuctionItemRoleView_struct.h"
#include "GetGuildRepositoryRoleViewArg_struct.h"
#include "GetGuildRepositoryRoleViewRes_struct.h"
#include "QueryGuildWelfareAwardArg_struct.h"
#include "QueryGuildWelfareAwardRes_struct.h"

#include "GuildBuilding_struct.h"
#include "QueryGuildBuildingInfoArg_struct.h"
#include "QueryGuildBuildingInfoRes_struct.h"

#include "GuildCrystal_struct.h"
#include "QueryGuildCrystalInfoArg_struct.h"
#include "QueryGuildCrystalInfoRes_struct.h"

#include "box/service_context.hh"
#include "error/make_error_code.h"
#include "fwd.h"
#include "guild/guild.h"
#include "guildservicequery.enum.h"

#include "logic/guild_application_logic.h"
#include "logic/guild_brief_logic.h"
#include "logic/guild_members_logic.h"
#include "logic/guild_welfare_logic.h"

#include "module/guild_module_def.h"

#include "token/service_token_mgr.hpp"

namespace guild_service {
bool GuildServiceQueryContext::Start(kratos::service::ServiceContext *context) {
  if (!GuildServiceQueryContext::Init(context)) {
    return false;
  }

  return register_service(std::string(kGuildServicePrefix) +
                          std::string(kGuildServiceQueryName));
}

bool GuildServiceQueryContext::Stop() {
  LOG_INFO("公会查询服务关闭");

  if (!unregister_service(std::string(kGuildServicePrefix) +
                          std::string(kGuildServiceQueryName))) {
    return false;
  }

  return GuildServiceQueryContext::Uninit();
}

bool GuildServiceQueryContext::Init(kratos::service::ServiceContext *context) {
  if (!common::singleton_start<common::service_logger>(
          context, kGuildServiceQueryName)) {
    LOG_FAIL("公会查询服务启动失败");
    return false;
  }

  LOG_INFO("公会查询服务启动");

  if (!common::singleton_start<common::service_context>(context)) {
    LOG_FAIL("公会查询服务启动失败");
    return false;
  }
  
  if (!common::singleton_start<common::util>(context)) {
    LOG_FAIL("公会查询服务启动失败");
    return false;
  }

  if (!common::singleton_start<common::service_redis_client>(context)) {
    LOG_FAIL("公会查询服务启动失败");
    return false;
  }

  std::string redis_host(kRedisHost);
  int32_t redis_port = kRedisPort;
  std::string redis_user(kRedisUser);
  std::string redis_passwd(kRedisPasswd);

  {// config.redis
    auto* config_ptr = ServiceContextSingleton()->get_config().get_config_ptr();
    if (!config_ptr) {
      LOG_FAIL("公会查询服务启动失败");
      return false;
    }
    if (config_ptr->has("redis")) {
      if (config_ptr->has("redis.host")) {
        redis_host = config_ptr->getString("redis.host");
      }
      if (config_ptr->has("redis.port")) {
        redis_port = config_ptr->getInt32("redis.port");
      }
      if (config_ptr->has("redis.user")) {
        redis_user = config_ptr->getString("redis.user");
      }
      if (config_ptr->has("redis.passwd")) {
        redis_passwd = config_ptr->getString("redis.passwd");
      }
    }
  }

  if (!redis_add_host(kGuildServiceQueryName, redis_host, redis_port,
                      redis_user, redis_passwd)) {
    LOG_FAIL("公会查询服务启动失败");
    return false;
  }

  if (!common::singleton_start<common::service_time_scheduler>(context)) {
    LOG_FAIL("公会查询服务启动失败");
    return false;
  }

  return true;
}

bool GuildServiceQueryContext::Uninit() {
  return common::singleton_stop<common::service_time_scheduler>() &&
         common::singleton_stop<common::service_redis_client>() &&
         common::singleton_stop<common::util>() &&
         common::singleton_stop<common::service_context>() &&
         common::singleton_stop<common::service_logger>();
}

void GuildServiceQueryContext::Tick(time_t ms) {
  common::singleton_update<common::service_redis_client>(ms);
  common::singleton_update<common::service_time_scheduler>(ms);

  // 上一次加载公会模块的时间戳
  static time_t m_last_load_timestamp = 0;
  if (ms - m_last_load_timestamp > kLoadGuildModuleInterval) {
    m_last_load_timestamp = ms;
    // GuildServiceQuerySingleton->LoadGuildAsync();
  }
}

void GuildServiceQueryContext::GetGuildBrief(rpc::StubCallPtr call,
    const GetGuildBriefArg &arg, std::shared_ptr<GetGuildBriefRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceQueryName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }
  error_code ec(ErrorCode::ERR_SUCCESS);
  
  if (!GuildBriefLogic::GetGuildModuleBriefByRole(role_uuid, res->brief, ec)) {
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }

  res->result = static_cast<ErrorCode>(ec.value());

  // LOG_INFO("查询公会信息成功 公会id:%llu 角色唯一id:%llu 查询类型:%d",
  //          arg.guild_id, arg.role_uuid, arg.type);
}

void GuildServiceQueryContext::GetGuildMember(rpc::StubCallPtr call,
    const GetGuildMemberArg &arg, std::shared_ptr<GetGuildMemberRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceQueryName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }
  error_code ec(ErrorCode::ERR_SUCCESS);
  if (!GuildMembersLogic::GetGuildMember(role_uuid, arg.member_uuid,
                                         res->member, ec)) {
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }

  res->result = static_cast<ErrorCode>(ec.value());

  // LOG_INFO("查询公会信息成功 公会id:%llu 角色唯一id:%llu 查询类型:%d",
  //          arg.guild_id, arg.role_uuid, arg.type);
}

void GuildServiceQueryContext::GetGuildBriefList(rpc::StubCallPtr call,
    const GetGuildBriefListArg &arg,
    std::shared_ptr<GetGuildBriefListRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceQueryName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }
  error_code ec(ErrorCode::ERR_SUCCESS);

  try {
    if (!GuildBriefLogic::GetGuildBriefList(role_uuid, arg.count,
                                            res->brief_list, ec)) {
      // LOG_WARN("查询公会简略信息失败 角色唯一id:%llu", arg.role_uuid);
      res->result = static_cast<ErrorCode>(ec.value());
      return;
    }
  } catch (std::exception &ex) {
    LOG_EXCEPT("查询公会简略信息 异常:%s", ex.what());
    return;
  }

  res->result = static_cast<ErrorCode>(ec.value());

  // LOG_INFO("查询公会简略信息成功 角色唯一id:%llu 公会数量:%zu",
  // arg.role_uuid, res->guild_id_list.size());
}

void GuildServiceQueryContext::SearchGuild(rpc::StubCallPtr call,
    const SearchGuildArg &arg, std::shared_ptr<SearchGuildRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceQueryName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }
  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildBriefLogic::SearchGuild(role_uuid, arg.name, res->brief, ec)) {
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }

  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceQueryContext::GetGuildApplication(rpc::StubCallPtr call,
    const GetGuildApplicationArg &arg,
    std::shared_ptr<GetGuildApplicationRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceQueryName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }
  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildApplicationLogic::GetGuildModuleApplication(role_uuid,
                                                  res->application, ec)) {
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }

  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceQueryContext::GetGuildMembers(rpc::StubCallPtr call,
    const GetGuildMembersArg &arg, std::shared_ptr<GetGuildMembersRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceQueryName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }
  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildMembersLogic::GetGuildModuleMembers(role_uuid,
                                                  res->member_list, ec)) {
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }

  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceQueryContext::GetGuildRepositoryRoleView(rpc::StubCallPtr call,
      const GetGuildRepositoryRoleViewArg &arg,
      std::shared_ptr<GetGuildRepositoryRoleViewRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceQueryName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }
  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildMembersLogic::GetGuildRepositoryRoleView(role_uuid, *res, ec)) {
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }

  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceQueryContext::QueryGuildWelfareAward(rpc::StubCallPtr call,
      const QueryGuildWelfareAwardArg &arg,
      std::shared_ptr<QueryGuildWelfareAwardRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceQueryName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }
  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildMembersLogic::QueryGuildWelfareAward(role_uuid, res->award, ec)) {
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }

  res->result = static_cast<ErrorCode>(ec.value());

}
void GuildServiceQueryContext::QueryGuildBuildingInfo(rpc::StubCallPtr call,
      const QueryGuildBuildingInfoArg &arg,
      std::shared_ptr<QueryGuildBuildingInfoRes> &res) {
  error_code ec(ErrorCode::ERR_SUCCESS);
  // TODO
  res->result = static_cast<ErrorCode>(ec.value());
}
  
void GuildServiceQueryContext::QueryGuildCrystalInfo(rpc::StubCallPtr call,
      const QueryGuildCrystalInfoArg &arg,
      std::shared_ptr<QueryGuildCrystalInfoRes> &res) {
  error_code ec(ErrorCode::ERR_SUCCESS);
  // TODO
  res->result = static_cast<ErrorCode>(ec.value());
}


};  // namespace guild_service